HarmonyOS-鸿蒙app开发 —基于java安全权限开发指导

HarmonyOS-鸿蒙app开发 —基于java安全权限开发指导

场景介绍

HarmonyOS支持开发者自定义权限来保护能力或接口,同时开发者也可申请权限来访问受权限保护的对象。

权限申请

开发者需要在config.json文件中的“reqPermissions”字段中声明所需要的权限。

{
“module”: {
“reqPermissions”: [
{
“name”: “ohos.permission.CAMERA”,
“reason”: “$string:permreason_camera”,
“usedScene”:
{
“ability”: [“com.mycamera.Ability”, “com.mycamera.AbilityBackground”],
“when”: “always”
}
},{

}
]
}
}

权限申请格式采用数组格式,可支持同时申请多个权限,权限个数最多不能超过1024个。

表1 reqPermissions权限申请字段说明

值说明

类型

取值范围

默认值

规则约束

name

必须,填写需要使用的权限名称。

字符串

自定义

未填写时,解析失败。

reason

可选,当申请的权限为user_grant权限时此字段必填。

描述申请权限的原因。

字符串

显示文字长度不能超过256个字节。

user_grant权限必填,否则不允许在应用市场上架。

需做多语种适配。

usedScene

可选,当申请的权限为user_grant权限时此字段必填。

描述权限使用的场景和时机。场景类型有:ability、when(调用时机)。可配置多个ability。

ability:字符串数组

when:字符串

ability:ability的名称

when:inuse(使用时)、always(始终)

ability:空

when:inuse

user_grant权限必填ability,可选填when。

如果声明使用的权限的grantMode是system_grant,则权限会在当应用安装的时候被自动授予。

如果声明使用的权限的grantMode是user_grant,则必须经用户手动授权(用户在弹框中授权或进入权限设置界面授权)才可使用。用户会看到reason字段中填写的理由,来帮助用户决定是否给予授权。

说明

对于授权方式为user_grant的权限,每一次执行需要这一权限的操作时,都需要检查自身是否有该权限。当自身具有权限时,才可继续执行,否则应用需要请求用户授予权限。示例参见动态申请权限开发步骤

自定义权限

开发者需要在config.json文件中的“defPermissions”字段中自定义所需的权限:

{
“module”: {
“defPermissions”: [
{
“name”: “com.myability.permission.MYPERMISSION”,
“grantMode”: “system_grant”,
“availableScope”: [“signature”]
}, {

}
]
}
}

权限定义格式采用数组格式,可支持同时定义多个权限,自定义的权限个数最多不能超过1024个。权限定义的字段描述详见表2

表2 defPermissions权限定义字段说明

值说明

类型

取值范围

默认值

规则约束

name

必填,权限名称。为最大可能避免重名,采用反向域公司名+应用名+权限名组合。

字符串

自定义

第三方应用不允许填写系统存在的权限,否则安装失败。未填写解析失败。权限名长度不能超过256个字符。

grantMode

必填,权限授予方式。

字符串

  • user_grant(用户授权)
  • system_grant(系统授权)

取值含义请参见:表3

system_grant

未填值或填写了取值范围以外的值时,自动赋予默认值;

不允许第三方应用填写user_grant,填写后会自动赋予默认值。

availableScope

选填,权限限制范围。不填则表示此权限对所有应用开放。

字符串数组

  • signature
  • privileged
  • restricted

取值含义请参见:表4

填写取值范围以外的值时,权限限制范围不生效。

由于第三方应用并不在restricted的范围内,很少会出现权限定义者不能访问自身定义的权限的情况,所以不允许三方应用填写restricted。

label

选填,权限的简短描述,若未填写,则使用到简短描述的地方由权限名取代。

字符串

自定义

需要多语种适配。

description

选填,权限的详细描述,若未填写,则使用到详细描述的地方由label取代。

字符串

自定义

需要多语种适配。

表3 权限授予方式字段说明

授予方式

(grantMode)

说明

自定义权限是否可指定该级别

取值样例

system_grant

“config.json”里面声明,安装后系统自动授予。

GET_NETWORK_INFO 、GET_WIFI_INFO

user_grant

“config.json”里面声明,并在使用时动态申请,用户授权后才可使用。

否,如自定义则强制修改为system_grant。

CAMERA、MICROPHONE

表4 权限限制范围字段说明

权限范围

(availableScope)

说明

自定义权限是否可指定该级别

取值样例

restricted

需要开发者申请对应证书后才能被使用的特殊权限。

WRITE_CONTACTS、READ_CONTACTS

signature

权限定义方和使用方的签名一致。需在“config.json”里面声明后,由权限管理模块负责签名校验一致后,可使用。

对应用(或Ability)操作的系统接口上由系统定义权限以及应用自定义的权限。

如:发现某Ability,连接某Ability。

privileged

预置在系统版本中的特权应用可申请的权限。

SET_TIME、MANAGE_USER_STORAGE

访问权限控制

  • Ability的访问权限控制

    在config.json中填写“abilities”的“permissions”字段,即只有拥有该权限的应用可访问此Ability。下面的例子表明只有拥有“ohos.permission.CAMERA”权限的应用可以访问此ability。

“abilities”: [
{
“name”: “.MainAbility”,
“description”: “$string:description_main_ability”,
“icon”: “$media:hiworld”,
“label”: “HiCamera”,
“launchType”: “standard”,
“orientation”: “portrait”,
“visible”: false,
“permissions”: [
“ohos.permission.CAMERA”
],
}
]

  • 表5 权限保护字段说明

    值说明

    类型

    取值范围

    默认值

    规则约束

    permissions

    选填,权限名称。用以表示此ability受哪个权限保护,即只有拥有此权限的应用可访问此ability。

    字符串数组

    自定义

    目前仅支持填写一个权限名,若填写多个权限名,仅第一个权限名称有效。

  • Ability接口的访问权限控制

    在Ability实现中,如需要对特定接口对调用者做访问控制,可在服务侧的接口实现中,主动通过verifyCallingPermission、verifyCallingOrSelfPermission来检查访问者是否拥有所需要的权限。

if (verifyCallingPermission(“ohos.permission.CAMERA”) != IBundleManager.PERMISSION_GRANTED) {
// 调用者无权限,做错误处理
}
// 调用者权限校验通过,开始提供服务

API接口说明

表6 应用权限接口说明

接口原型

接口详细描述

int verifyPermission(String permissionName, int pid, int uid)

接口功能:查询指定PID、UID的应用是否已被授予某权限

输入参数:permissionName:权限名;pid:进程id;uid:uid

输出参数:无

返回值: IBundleManager.PERMISSION_DENIED、IBundleManager.PERMISSION_GRANTED

int verifyCallingPermission(String permissionName)

接口功能:查询IPC跨进程调用方的进程是否已被授予某权限

输入参数:permissionName:权限名

输出参数:无

返回值: IBundleManager.PERMISSION_DENIED、IBundleManager.PERMISSION_GRANTED

int verifySelfPermission(String permissionName)

接口功能:查询自身进程是否已被授予某权限

输入参数:permissionName:权限名

输出参数:无

返回值: IBundleManager.PERMISSION_DENIED、IBundleManager.PERMISSION_GRANTED

int verifyCallingOrSelfPermission(String permissionName)

接口功能:当有远端调用检查远端是否有权限,否则检查自身是否拥有权限

输入参数:permissionName:权限名

输出参数:无

返回值: IBundleManager.PERMISSION_DENIED、IBundleManager.PERMISSION_GRANTED

boolean canRequestPermission(String permissionName)

接口功能:向系统权限管理模块查询某权限是否不再弹框授权了

输入参数:permissionName:权限名

输出参数:无

返回值:true允许弹框,false不允许弹框

void requestPermissionsFromUser (String[] permissions, int requestCode)

接口功能:向系统权限管理模块申请权限(接口可支持一次申请多个。若下一步操作涉及到多个敏感权限,可以这么用,其他情况建议不要这么用。因为弹框还是按权限组一个个去弹框,耗时比较长。用到哪个权限就去申请哪个)

输入参数: permissions:权限名列表;requestCode: 请求应答会带回此编码以匹配本次申请的权限请求

输出参数:无

返回值:无

void onRequestPermissionsFromUserResult (int requestCode, String[] permissions, int[] grantResults)

接口功能:调用requestPermissionsFromUser后的应答接口

输入参数:requestCode:requestPermission中传入的requestCode;permissions:申请的权限名;grantResults:申请权限的结果

输出参数:无

返回值:无

动态申请权限开发步骤

  1. 在config.json文件中声明所需要的权限。

{
“module”: {
“reqPermissions”: [
{
“name”: “ohos.permission.CAMERA”,
“reason”: “$string:permreason_camera”,
“usedScene”: {
“ability”: [“com.mycamera.Ability”, “com.mycamera.AbilityBackground”],
“when”: “always”}
}, {

}
]
}
}

  1. 使用ohos.app.Context.verifySelfPermission接口查询应用是否已被授予该权限。
    • 如果已被授予权限,可以结束权限申请流程。
    • 如果未被授予权限,继续执行下一步。
  2. 使用canRequestPermission查询是否可动态申请。
    • 如果不可动态申请,说明已被用户或系统永久禁止授权,可以结束权限申请流程。
    • 如果可动态申请,使用requestPermissionFromUser动态申请权限。

if (verifySelfPermission(“ohos.permission.CAMERA”) != IBundleManager.PERMISSION_GRANTED) {
// 应用未被授予权限
if (canRequestPermission(“ohos.permission.CAMERA”)) {
// 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
requestPermissionsFromUser(
new String[] { “ohos.permission.CAMERA” } , MY_PERMISSIONS_REQUEST_CAMERA);
} else {
// 显示应用需要权限的理由,提示用户进入设置授权
}
} else {
// 权限已被授予
}

通过重写ohos.aafwk.ability.Ability的回调函数onRequestPermissionsFromUserResult接收授予结果。

 

@Override
public void onRequestPermissionsFromUserResult (int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CAMERA: {
// 匹配requestPermissions的requestCode
if (grantResults.length > 0
&& grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
// 权限被授予
// 注意:因时间差导致接口权限检查时有无权限,所以对那些因无权限而抛异常的接口进行异常捕获处理
} else {
// 权限被拒绝
}
return;
}
}
}

0 0 投票数
文章评分
订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x